#include "Polygon.h"

namespace poly
{
	Polygon Polygon::transform( float44 const & mat ) const
	{
		Polygon out;
		for( Polygon::const_iterator v = begin();
			v != end();
			v++ )
		{
			out.push_back( transformCoord( *v, mat ) );
		}

		return out;
	}

	float Polygon::area() const
	{
		float out = 0;
		for( size_t i = size()-1, j = 0; j < size(); i = j, j++ )
		{
			out += ((*this)[i].x - (*this)[j].x)*((*this)[j].y + (*this)[i].y)/2;
		}

		return out;
	}

	float3 Polygon::center() const
	{
		float area = 0;
		float3 out(0, 0, 0);

		for( size_t i = size()-1, j = 0; j < size(); i = j, j++ )
		{
			area += ((*this)[i].x - (*this)[j].x)*((*this)[j].y + (*this)[i].y)/2;

			float factor = ((*this)[i].x*(*this)[j].y - (*this)[j].x*(*this)[i].y);

			out.x += ((*this)[i].x + (*this)[j].x)*factor;
			out.y += ((*this)[i].y + (*this)[j].y)*factor;
		}

		return out/6/area;
	}

	float33 Polygon::momentOfInertia( ) const
	{
		float33 out = zero33();
		Polygon const & Q = *this;
		for( int i = size()-1, j = 0; j < size(); i = j, j++ )
		{
			float x0	= Q[i].x;
			float y0	= Q[i].y;
			float x01	= Q[j].x-Q[i].x;
			float y01	= Q[j].y-Q[i].y;

			float x0sq	= x0*x0;
			float x01sq	= x01*x01;
			float y0sq	= y0*y0;
			float y01sq	= y01*y01;

			float factor1 =
				+ x01sq*y01/4
				+ 2*x0*x01*y01/3
				+ x01sq*y0/3
				+ x0sq*y01/2
				+ x0*x01*y0
				+ x0sq*y0;

			float xx = -x01*factor1;

			float factor2 =
				+ x01*y01sq/4
				+ x0*y01sq/3
				+ 2*x01*y0*y01/3
				+ x01*y0sq/2
				+ x0*y0sq;

			float yy = +y01*factor2;

			float xy = +y01*factor1/2;

			out.xx += yy;
			out.yy += xx;
			out.zz += xx + yy;

			out.xy += -xy;
			out.yx += -xy;
		}

		return out;
	}
}